using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using App.Controlador;
using App.Modelo;
using App.Modelo.Attributes;
using App.Modelo.Menu;
using App.Seguridad.Vista.Menu;

namespace App.Seguridad.Vista.Forms
{
    [Formulario("Grupos")]
    public class DetalleGrupo : Form
    {
        private readonly PerfilesMenuControlador menuControlador;
        private readonly TreeNode root;

        public ControladoraGrupos Grupos;

        public ControladoraPerfiles Perfiles;
        private Grupo _Grupo;
        private IContainer components;
        private ImageList imageList1;
        private MenuStrip menuStrip1;
        private TreeView tree;


        public DetalleGrupo()
        {
            InitializeComponent();

            Grupos = ModuloSeguridad.Instance.FabricaControladoras.Factory<ControladoraGrupos>();
            Perfiles = ModuloSeguridad.Instance.FabricaControladoras.Factory<ControladoraPerfiles>();

            menuControlador = new PerfilesMenuControlador(menuStrip1);
            menuControlador.ExecuteCommand += MenuManager_ExecuteCommand;


            root = new TreeNode
                       {
                           ImageKey = "grupo"
                       };


            foreach (Formulario form in Grupos.ListFormularios())
            {
                var t = new TreeNode
                            {
                                Text = form.Descripcion,
                                Tag = form,
                                ImageKey = "formulario"
                            };

                t.Nodes.AddRange((from fun in form.Funciones
                                  select new TreeNode
                                             {
                                                 Text = fun.ToString(),
                                                 Tag = fun,
                                                 ImageKey = fun.Nombre
                                             }).ToArray());
                root.Nodes.Add(t);
            }

            tree.Nodes.Add(root);
            root.Expand();


            tree.AfterCheck += tree_AfterCheck;
        }

        public Grupo Grupo
        {
            get { return _Grupo; }
            set
            {
                _Grupo = value;
                root.Text = value.Nombre;
                root.Tag = value;
                _actualizarTree(value);
            }
        }

        [Comando("alta")]
        public void Alta()
        {
            menuControlador.Model = new Modelo.Menu.MenuContenedor(new[]
                                                             {
                                                                 new MenuBoton("Guardar", "bullet_disk", "Grupos/alta"),
                                                                 new MenuBoton("Cerrar", "cancel", "cerrar")
                                                             });

            Grupo = new Grupo();

            ModuloSeguridad.Instance.AbrirFormulario(this);

            tree.Nodes[0].BeginEdit();
        }

        public void Modificar(Grupo g)
        {
            menuControlador.Model = new Modelo.Menu.MenuContenedor(new MenuBaseItem[]
                                                             {
                                                                 new MenuBoton("Guardar", "bullet_disk",
                                                                              "Grupos/modificar"),
                                                                 new MenuBoton("Cerrar", "cancel", "cerrar"),
                                                             });
            Grupo = g;
            ModuloSeguridad.Instance.AbrirFormulario(this);
        }

        private void tree_AfterCheck(object sender, TreeViewEventArgs e)
        {
            if (e.Node.Checked)
            {
                if (e.Node.Nodes != null)
                    foreach (TreeNode it in e.Node.Nodes)
                        it.Checked = true;
            }
        }

        private void _actualizarTree(Grupo grupo)
        {
            IList<Perfil> perfiles = Perfiles.Get(Grupo);


            foreach (TreeNode form in root.Nodes)
            {
                IEnumerable<Perfil> funciones = perfiles.Where(
                    perfil => perfil.Formulario.Equals(form.Tag));

                form.Checked = form.Nodes.Count <= funciones.Count();

                foreach (TreeNode fun in form.Nodes)
                {
                    fun.Checked = funciones.Count(perfil => perfil.Funcion.Equals(fun.Tag)) > 0;
                }
            }
        }

        private void MenuManager_ExecuteCommand(object sender, MenuEjecutarComandoEventArgs e)
        {
            switch (e.Item.Command)
            {
                case "Grupos/modificar":
                    guardar();
                    break;
                case "Grupos/alta":
                    guardarAlta();
                    break;
            }
        }

        private void guardar()
        {
            Validate();
            Grupos.Update(Grupo, _getPerfiles());
            Close();
        }

        private IList<Perfil> _getPerfiles()
        {
            var perfiles = new List<Perfil>();
            foreach (TreeNode form in root.Nodes)
            {
                perfiles.AddRange(from TreeNode funcion in form.Nodes
                                  where funcion.Checked
                                  select new Perfil
                                             {
                                                 Grupo = Grupo,
                                                 Formulario = (Formulario) form.Tag,
                                                 Funcion = (Funcion) funcion.Tag
                                             });
            }
            return perfiles;
        }

        private void guardarAlta()
        {
            Validate();
            Grupos.Create(Grupo, _getPerfiles());
            Close();
        }

        private void InitializeComponent()
        {
            components = new Container();
            var resources = new ComponentResourceManager(typeof (DetalleGrupo));
            menuStrip1 = new MenuStrip();
            tree = new TreeView();
            imageList1 = new ImageList(components);
            SuspendLayout();
            // 
            // menuStrip1
            // 
            menuStrip1.Location = new Point(0, 0);
            menuStrip1.Name = "menuStrip1";
            menuStrip1.Size = new Size(292, 24);
            menuStrip1.TabIndex = 0;
            menuStrip1.Text = "menuStrip1";
            // 
            // tree
            // 
            tree.CheckBoxes = true;
            tree.Dock = DockStyle.Fill;
            tree.ImageIndex = 0;
            tree.ImageList = imageList1;
            tree.LabelEdit = true;
            tree.Location = new Point(0, 24);
            tree.Name = "tree";
            tree.SelectedImageIndex = 0;
            tree.Size = new Size(292, 244);
            tree.TabIndex = 1;
            tree.AfterLabelEdit += tree_AfterLabelEdit;
            // 
            // imageList1
            // 
            imageList1.ImageStream = ((ImageListStreamer) (resources.GetObject("imageList1.ImageStream")));
            imageList1.TransparentColor = Color.Transparent;
            imageList1.Images.SetKeyName(0, "grupo");
            imageList1.Images.SetKeyName(1, "formulario");
            imageList1.Images.SetKeyName(2, "alta");
            imageList1.Images.SetKeyName(3, "baja");
            imageList1.Images.SetKeyName(4, "modificar");
            imageList1.Images.SetKeyName(5, "ver");
            // 
            // DetalleGrupo
            // 
            ClientSize = new Size(292, 268);
            Controls.Add(tree);
            Controls.Add(menuStrip1);
            Font = new Font("Arial", 9.75F, FontStyle.Regular, GraphicsUnit.Point, ((0)));
            MainMenuStrip = menuStrip1;
            Name = "DetalleGrupo";
            ResumeLayout(false);
            PerformLayout();
        }

        private void tree_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
        {
            e.CancelEdit = false;

            if (e.Node.Tag is Grupo)
            {
                var grupo = (Grupo) e.Node.Tag;
                e.Node.Text = grupo.Nombre = e.Label;
            }
            else if (e.Node.Tag is Formulario)
            {
                var form = (Formulario) e.Node.Tag;
                e.Node.Text = form.Descripcion = e.Label;
            }
            else
            {
                e.CancelEdit = true;
            }
        }
    }
}